//通过类的方式来进行封装,会让代码更加具有复用性
class WxRequest {

	//定义实例属性,用来设置默认请求参数
	defaults = {
		baseURL: '',//基准路径
		url: '',
		data: null,
		method: 'GET',
		header: {
			'Content-type': 'application/json'//设置数据的交互格式
		},
		timeout: 6000,//默认超时时长
		isLoading: true//控制是否使用默认的loading
	}

	//定义默认拦截器对象,方便在请求之前以及响应以后进行逻辑处理
	interceptors = {
		//请求拦截器
		request: (config) => config,

		//响应拦截器
		response: (response) => response
	}

	//定义数组队列，用来存储请求队列和请求标识
	queue = []

	//1.在实例化时
	//传入的参数会被constructor的形参接收
	constructor(params = {}) {
		//通过Object.assign方法合并请求参数
		this.defaults = Object.assign({}, this.defaults, params)
	}

	//2.调用实例方法时
	request(options) {
		this.timeId && clearTimeout(this.timeId)

		//合并完整的请求地址
		options.url = this.defaults.baseURL + options.url

		//合并请求参数
		options = { ...this.defaults, ...options }

		//在请求发送之前,添加 loading 效果
		// wx.showLoading()

		if (options.isLoading && options.method !== 'UPLOAD') {
			//判断 queue 队列是否为空，如果是，就显示loading，否则不显示loading
			this.queue.length === 0 && wx.showLoading()
		}


		//向 queue 数组队列添加请求标识，每个标识代表一个请求
		this.queue.push('request')

		//在请求发送之前,调用请求拦截器,新增和修改请求参数
		options = this.interceptors.request(options)

		return new Promise((resolve, reject) => {
			if (options.method === 'UPLOAD') {
				wx.uploadFile({
					...options,
					success: (res) => {
						res.data = JSON.parse(res.data)
						const mergeRes = Object.assign({}, res, { config: options, isSuccess: true })
						resolve(this.interceptors.response(mergeRes))
					},
					fail: (err) => {
						const mergeErr = Object.assign({}, err, { config: options, isSuccess: false })
						reject(this.interceptors.response(mergeErr))
					}
				})
			} else {
				wx.request({
					...options,
					success: (res) => {
						//合并参数,连同请求参数(方便代码调试或其他逻辑处理),传递给响应拦截器
						const mergeRes = Object.assign({}, res, { config: options, isSuccess: true })

						resolve(this.interceptors.response(mergeRes))
					},
					fail: (err) => {
						//不管成功响应还是失败响应,都需要调用响应拦截器
						const mergeErr = Object.assign({}, err, { config: options, isSuccess: false })

						reject(this.interceptors.response(mergeErr))
					},
					complete: () => {
						if (options.isLoading) {
							//每次从 queue 队列中删除一个标识
							this.queue.pop()

							//相互依赖的请求之间防抖
							this.queue.length === 0 && this.queue.push('request')

							this.timeId = setTimeout(() => {
								this.queue.pop()
								this.queue.length === 0 && wx.hideLoading()
								clearTimeout(this.timeId)
							}, 1)
						}
					}
				})
			}
		})
	}

	//3.请求便捷方法(组织参数传递给request请求方法)
	get(url, data = {}, config = {}) {
		return this.request(Object.assign({ url, data, method: 'GET' }, config))
	}

	delete(url, data = {}, config = {}) {
		return this.request(Object.assign({ url, data, method: 'DELETE' }, config))
	}

	post(url, data = {}, config = {}) {
		return this.request(Object.assign({ url, data, method: 'POST' }, config))
	}

	put(url, data = {}, config = {}) {
		return this.request(Object.assign({ url, data, method: 'PUT' }, config))
	}

	//处理并发请求
	all(...promise) {
		console.log(promise);
		return Promise.all(promise)
	}

	upload(url, filePath, name = 'file', config = {}) {
		return this.request(
			Object.assign({ url, filePath, name, method: 'UPLOAD' }, config
			)
		)
	}
}

export default WxRequest